home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Zoners Half-Life Tools / hlrad / lerp.cpp < prev    next >
C/C++ Source or Header  |  2002-12-09  |  21KB  |  614 lines

  1. #include "qrad.h"
  2.  
  3. int             g_lerp_enabled = DEFAULT_LERP_ENABLED;
  4.  
  5. // =====================================================================================
  6. //  TestWallIntersectTri
  7. //      Returns true if wall polygon intersects patch polygon
  8. // =====================================================================================
  9. static bool     TestWallIntersectTri(const lerpTriangulation_t* const trian, const vec3_t p1, const vec3_t p2, const vec3_t p3)
  10. {
  11.     int             x;
  12.     const lerpWall_t* wall = trian->walls;
  13.     dplane_t        plane;
  14.  
  15.     plane_from_points(p1, p2, p3, &plane);
  16.  
  17.     // Try first 'vertical' side
  18.     // Since we test each of the 3 segments from patch against wall, only one side of wall needs testing inside 
  19.     // patch (since they either dont intersect at all at this point, or both line segments intersect inside)
  20.     for (x = 0; x < trian->numwalls; x++, wall++)
  21.     {
  22.         vec3_t          point;
  23.  
  24.         // Try side A
  25.         if (intersect_linesegment_plane(&plane, wall->vertex[0], wall->vertex[3], point))
  26.         {
  27.             if (point_in_tri(point, &plane, p1, p2, p3))
  28.             {
  29. #if 0
  30.                 Verbose
  31.                     ("Wall side A point @ (%4.3f %4.3f %4.3f) inside patch (%4.3f %4.3f %4.3f) (%4.3f %4.3f %4.3f) (%4.3f %4.3f %4.3f)\n",
  32.                      point[0], point[1], point[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], p3[0], p3[1], p3[2]);
  33. #endif
  34.                 return true;
  35.             }
  36.         }
  37.     }
  38.     return false;
  39. }
  40.  
  41. // =====================================================================================
  42. //  TestLineSegmentIntersectWall
  43. //      Returns true if line would hit the 'wall' (to fix light streaking)
  44. // =====================================================================================
  45. static bool     TestLineSegmentIntersectWall(const lerpTriangulation_t* const trian, const vec3_t p1, const vec3_t p2)
  46. {
  47.     int             x;
  48.     const lerpWall_t* wall = trian->walls;
  49.  
  50.     for (x = 0; x < trian->numwalls; x++, wall++)
  51.     {
  52.         vec3_t          point;
  53.  
  54.         if (intersect_linesegment_plane(&wall->plane, p1, p2, point))
  55.         {
  56.             if (point_in_wall(wall, point))
  57.             {
  58. #if 0
  59.                 Verbose
  60.                     ("Tested point @ (%4.3f %4.3f %4.3f) blocks segment from (%4.3f %4.3f %4.3f) to (%4.3f %4.3f %4.3f) intersects wall\n",
  61.                      point[0], point[1], point[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2]);
  62. #endif
  63.                 return true;
  64.             }
  65.         }
  66.     }
  67.     return false;
  68. }
  69.  
  70. // =====================================================================================
  71. //  TestTriIntersectWall
  72. //      Returns true if line would hit the 'wall' (to fix light streaking)
  73. // =====================================================================================
  74. static bool     TestTriIntersectWall(const lerpTriangulation_t* trian, const vec3_t p1, const vec3_t p2,
  75.                                      const vec3_t p3)
  76. {
  77.     if (TestLineSegmentIntersectWall(trian, p1, p2) || TestLineSegmentIntersectWall(trian, p1, p3)
  78.         || TestLineSegmentIntersectWall(trian, p2, p3))
  79.     {
  80.         return true;
  81.     }
  82.     return false;
  83. }
  84.  
  85. // =====================================================================================
  86. //  LerpTriangle
  87. //      pt1 must be closest point
  88. // =====================================================================================
  89. #ifdef ZHLT_TEXLIGHT
  90. static void     LerpTriangle(const lerpTriangulation_t* const trian, const vec3_t point, vec3_t result, const unsigned pt1, const unsigned pt2, const unsigned pt3, int style) //LRC
  91. #else
  92. static void     LerpTriangle(const lerpTriangulation_t* const trian, const vec3_t point, vec3_t result, const unsigned pt1, const unsigned pt2, const unsigned pt3)
  93. #endif
  94. {
  95.     patch_t*        p1;
  96.     patch_t*        p2;
  97.     patch_t*        p3;
  98.     vec3_t          base;
  99.     vec3_t          d1;
  100.     vec3_t          d2;
  101.     vec_t           x;
  102.     vec_t           y;
  103.     vec_t           y1;
  104.     vec_t           x2;
  105.     vec3_t          v;
  106.     dplane_t        ep1;
  107.     dplane_t        ep2;
  108.  
  109.     p1 = trian->points[pt1];
  110.     p2 = trian->points[pt2];
  111.     p3 = trian->points[pt3];
  112.  
  113. #ifdef ZHLT_TEXLIGHT
  114.     VectorCopy(*GetTotalLight(p1, style), base); //LRC
  115.     VectorSubtract(*GetTotalLight(p2, style), base, d1); //LRC
  116.     VectorSubtract(*GetTotalLight(p3, style), base, d2); //LRC
  117. #else
  118.     VectorCopy(p1->totallight, base);
  119.     VectorSubtract(p2->totallight, base, d1);
  120.     VectorSubtract(p3->totallight, base, d2);
  121. #endif
  122.  
  123.     // Get edge normals
  124.     VectorSubtract(p1->origin, p2->origin, v);
  125.     VectorNormalize(v);
  126.     CrossProduct(v, trian->plane->normal, ep1.normal);
  127.     ep1.dist = DotProduct(p1->origin, ep1.normal);
  128.  
  129.     VectorSubtract(p1->origin, p3->origin, v);
  130.     VectorNormalize(v);
  131.     CrossProduct(v, trian->plane->normal, ep2.normal);
  132.     ep2.dist = DotProduct(p1->origin, ep2.normal);
  133.  
  134.     x = DotProduct(point, ep1.normal) - ep1.dist;
  135.     y = DotProduct(point, ep2.normal) - ep2.dist;
  136.  
  137.     y1 = DotProduct(p2->origin, ep2.normal) - ep2.dist;
  138.     x2 = DotProduct(p3->origin, ep1.normal) - ep1.dist;
  139.  
  140.     VectorCopy(base, result);
  141.     if (fabs(x2) >= ON_EPSILON)
  142.     {
  143.         int             i;
  144.  
  145.         for (i = 0; i < 3; i++)
  146.         {
  147.             result[i] += x * d2[i] / x2;
  148.         }
  149.     }
  150.     if (fabs(y1) >= ON_EPSILON)
  151.     {
  152.         int             i;
  153.  
  154.         for (i = 0; i < 3; i++)
  155.         {
  156.             result[i] += y * d1[i] / y1;
  157.         }
  158.     }
  159. }
  160.  
  161. // =====================================================================================
  162. //  LerpNearest
  163. // =====================================================================================
  164. #ifdef ZHLT_TEXLIGHT
  165. static void     LerpNearest(const lerpTriangulation_t* const trian, vec3_t result, int style) //LRC
  166. #else
  167. static void     LerpNearest(const lerpTriangulation_t* const trian, vec3_t result)
  168. #endif
  169. {
  170.     unsigned        x;
  171.     unsigned        numpoints = trian->numpoints;
  172.     patch_t*        patch;
  173.  
  174.     // Find nearest in original face
  175.     for (x = 0; x < numpoints; x++)
  176.     {
  177.         patch = trian->points[trian->dists[x].patch];
  178.  
  179.         if (patch->faceNumber == trian->facenum)
  180.         {
  181. #ifdef ZHLT_TEXLIGHT
  182.             VectorCopy(*GetTotalLight(patch, style), result); //LRC
  183. #else
  184.             VectorCopy(patch->totallight, result);
  185. #endif
  186.             return;
  187.         }
  188.     }
  189.  
  190.     // If none in nearest face, settle for nearest
  191.     if (numpoints)
  192.     {
  193. #ifdef ZHLT_TEXLIGHT 
  194.         VectorCopy(*GetTotalLight(trian->points[trian->dists[0].patch], style), result); //LRC
  195. #else
  196.         VectorCopy(trian->points[trian->dists[0].patch]->totallight, result);
  197. #endif
  198.     }
  199.     else
  200.     {
  201.         VectorClear(result);
  202.     }
  203. }
  204.  
  205. // =====================================================================================
  206. //  LerpEdge
  207. // =====================================================================================
  208. #ifdef ZHLT_TEXLIGHT
  209. static bool     LerpEdge(const lerpTriangulation_t* const trian, const vec3_t point, vec3_t result, int style) //LRC
  210. #else
  211. static bool     LerpEdge(const lerpTriangulation_t* const trian, const vec3_t point, vec3_t result)
  212. #endif
  213. {
  214.     patch_t*        p1;
  215.     patch_t*        p2;
  216.     patch_t*        p3;
  217.     vec3_t          v1;
  218.     vec3_t          v2;
  219.     vec_t           d;
  220.  
  221.     p1 = trian->points[trian->dists[0].patch];
  222.     p2 = trian->points[trian->dists[1].patch];
  223.     p3 = trian->points[trian->dists[2].patch];
  224.  
  225.     VectorSubtract(point, p1->origin, v2);
  226.     VectorNormalize(v2);
  227.  
  228.     // Try nearest and 2
  229.     if (!TestLineSegmentIntersectWall(trian, p1->origin, p2->origin))
  230.     {
  231.         VectorSubtract(p2->origin, p1->origin, v1);
  232.         VectorNormalize(v1);
  233.         d = DotProduct(v2, v1);
  234.         if (d >= ON_EPSILON)
  235.         {
  236.             int             i;
  237.             vec_t           length1;
  238.             vec_t           length2;
  239.             vec3_t          segment;
  240.             vec_t           total_length;
  241.  
  242.             VectorSubtract(point, p1->origin, segment);
  243.             length1 = VectorLength(segment);
  244.             VectorSubtract(point, p2->origin, segment);
  245.             length2 = VectorLength(segment);
  246.             total_length = length1 + length2;
  247.  
  248.             for (i = 0; i < 3; i++)
  249.             {
  250. #ifdef ZHLT_TEXLIGHT
  251.                 result[i] = (((*GetTotalLight(p1, style))[i] * length2) + ((*GetTotalLight(p1, style))[i] * length1)) / total_length; //LRC
  252. #else
  253.                 result[i] = ((p1->totallight[i] * length2) + (p2->totallight[i] * length1)) / total_length;
  254. #endif
  255.             }
  256.             return true;
  257.         }
  258.     }
  259.  
  260.     // Try nearest and 3
  261.     if (!TestLineSegmentIntersectWall(trian, p1->origin, p3->origin))
  262.     {
  263.         VectorSubtract(p3->origin, p1->origin, v1);
  264.         VectorNormalize(v1);
  265.         d = DotProduct(v2, v1);
  266.         if (d >= ON_EPSILON)
  267.         {
  268.             int             i;
  269.             vec_t           length1;
  270.             vec_t           length2;
  271.             vec3_t          segment;
  272.             vec_t           total_length;
  273.  
  274.             VectorSubtract(point, p1->origin, segment);
  275.             length1 = VectorLength(segment);
  276.             VectorSubtract(point, p3->origin, segment);
  277.             length2 = VectorLength(segment);
  278.             total_length = length1 + length2;
  279.  
  280.             for (i = 0; i < 3; i++)
  281.             {
  282. #ifdef ZHLT_TEXLIGHT
  283.                 result[i] = (((*GetTotalLight(p1, style))[i] * length2) + ((*GetTotalLight(p3, style))[i] * length1)) / total_length; //LRC
  284.  
  285. #else
  286.                 result[i] = ((p1->totallight[i] * length2) + (p3->totallight[i] * length1)) / total_length;
  287. #endif
  288.             }
  289.             return true;
  290.         }
  291.     }
  292.     return false;
  293. }
  294.  
  295.  
  296. // =====================================================================================
  297. //
  298. //  SampleTriangulation
  299. //
  300. // =====================================================================================
  301.  
  302. // =====================================================================================
  303. //  dist_sorter
  304. // =====================================================================================
  305. static int CDECL dist_sorter(const void* p1, const void* p2)
  306. {
  307.     lerpDist_t*     dist1 = (lerpDist_t*) p1;
  308.     lerpDist_t*     dist2 = (lerpDist_t*) p2;
  309.  
  310.     if (dist1->dist < dist2->dist)
  311.     {
  312.         return -1;
  313.     }
  314.     else if (dist1->dist > dist2->dist)
  315.     {
  316.         return 1;
  317.     }
  318.     else
  319.     {
  320.         return 0;
  321.     }
  322. }
  323.  
  324. // =====================================================================================
  325. //  FindDists
  326. // =====================================================================================
  327. static void     FindDists(const lerpTriangulation_t* const trian, const vec3_t point)
  328. {
  329.     unsigned        x;
  330.     unsigned        numpoints = trian->numpoints;
  331.     patch_t**       patch = trian->points;
  332.     lerpDist_t*     dists = trian->dists;
  333.     vec3_t          delta;
  334.  
  335.     for (x = 0; x < numpoints; x++, patch++, dists++)
  336.     {
  337.         VectorSubtract((*patch)->origin, point, delta);
  338.         dists->dist = VectorLength(delta);
  339.         dists->patch = x;
  340.     }
  341.  
  342.     qsort((void*)trian->dists, (size_t) numpoints, sizeof(lerpDist_t), dist_sorter);
  343. }
  344.  
  345. // =====================================================================================
  346. //  SampleTriangulation
  347. // =====================================================================================
  348. #ifdef ZHLT_TEXLIGHT
  349. void            SampleTriangulation(const lerpTriangulation_t* const trian, vec3_t point, vec3_t result, int style) //LRC
  350. #else
  351. void            SampleTriangulation(const lerpTriangulation_t* const trian, vec3_t point, vec3_t result)
  352. #endif
  353. {
  354.     FindDists(trian, point);
  355.  
  356.     if ((trian->numpoints > 3) && (g_lerp_enabled))
  357.     {
  358.         unsigned        pt1;
  359.         unsigned        pt2;
  360.         unsigned        pt3;
  361.         vec_t*          p1;
  362.         vec_t*          p2;
  363.         vec_t*          p3;
  364.         dplane_t        plane;
  365.  
  366.         pt1 = trian->dists[0].patch;
  367.         pt2 = trian->dists[1].patch;
  368.         pt3 = trian->dists[2].patch;
  369.  
  370.         p1 = trian->points[pt1]->origin;
  371.         p2 = trian->points[pt2]->origin;
  372.         p3 = trian->points[pt3]->origin;
  373.  
  374.         plane_from_points(p1, p2, p3, &plane);
  375.         SnapToPlane(&plane, point, 0.0);
  376.         if (point_in_tri(point, &plane, p1, p2, p3))
  377.         {                                                  // TODO check edges/tri for blocking by wall
  378.             if (!TestWallIntersectTri(trian, p1, p2, p3) && !TestTriIntersectWall(trian, p1, p2, p3))
  379.             {
  380. #ifdef ZHLT_TEXLIGHT
  381.                 LerpTriangle(trian, point, result, pt1, pt2, pt3, style); //LRC
  382. #else
  383.                 LerpTriangle(trian, point, result, pt1, pt2, pt3);
  384. #endif
  385.                 return;
  386.             }
  387.         }
  388.         else
  389.         {
  390. #ifdef ZHLT_TEXLIGHT
  391.             if (LerpEdge(trian, point, result, style)) //LRC
  392. #else
  393.             if (LerpEdge(trian, point, result))
  394. #endif
  395.             {
  396.                 return;
  397.             }
  398.         }
  399.     }
  400.  
  401. #ifdef ZHLT_TEXLIGHT
  402.     LerpNearest(trian, result, style); //LRC
  403. #else
  404.     LerpNearest(trian, result);
  405. #endif
  406. }
  407.  
  408. // =====================================================================================
  409. //  AddPatchToTriangulation
  410. // =====================================================================================
  411. static void     AddPatchToTriangulation(lerpTriangulation_t* trian, patch_t* patch)
  412. {
  413.     if (!(patch->flags & ePatchFlagOutside))
  414.     {
  415.         int             pnum = trian->numpoints;
  416.  
  417.         if (pnum >= trian->maxpoints)
  418.         {
  419.             trian->points = (patch_t**)realloc(trian->points, sizeof(patch_t*) * (trian->maxpoints + DEFAULT_MAX_LERP_POINTS));
  420.  
  421.             hlassume(trian->points != NULL, assume_NoMemory);
  422.             memset(trian->points + trian->maxpoints, 0, sizeof(patch_t*) * DEFAULT_MAX_LERP_POINTS);   // clear the new block
  423.  
  424.             trian->maxpoints += DEFAULT_MAX_LERP_POINTS;
  425.         }
  426.  
  427.         trian->points[pnum] = patch;
  428.         trian->numpoints++;
  429.     }
  430. }
  431.  
  432. // =====================================================================================
  433. //  CreateWalls
  434. // =====================================================================================
  435. static void     CreateWalls(lerpTriangulation_t* trian, const dface_t* const face)
  436. {
  437.     const dplane_t* p = getPlaneFromFace(face);
  438.     int             facenum = face - g_dfaces;
  439.     int             x;
  440.  
  441.     for (x = 0; x < face->numedges; x++)
  442.     {
  443.         edgeshare_t*    es;
  444.         dface_t*        f2;
  445.         int             edgenum = g_dsurfedges[face->firstedge + x];
  446.  
  447.         if (edgenum > 0)
  448.         {
  449.             es = &g_edgeshare[edgenum];
  450.             f2 = es->faces[1];
  451.         }
  452.         else
  453.         {
  454.             es = &g_edgeshare[-edgenum];
  455.             f2 = es->faces[0];
  456.         }
  457.  
  458.         // Build Wall for non-coplanar neighbhors
  459.         if (f2 && !es->coplanar && VectorCompare(vec3_origin, es->interface_normal))
  460.         {
  461.             const dplane_t* plane = getPlaneFromFace(f2);
  462.  
  463.             // if plane isn't facing us, ignore it
  464.             if (DotProduct(plane->normal, g_face_centroids[facenum]) < plane->dist)
  465.             {
  466.                 continue;
  467.             }
  468.  
  469.             {
  470.                 vec3_t          delta;
  471.                 vec3_t          p0;
  472.                 vec3_t          p1;
  473.                 lerpWall_t*     wall;
  474.  
  475.                 if (trian->numwalls >= trian->maxwalls)
  476.                 {
  477.                     trian->walls =
  478.                         (lerpWall_t*)realloc(trian->walls, sizeof(lerpWall_t) * (trian->maxwalls + DEFAULT_MAX_LERP_WALLS));
  479.                     hlassume(trian->walls != NULL, assume_NoMemory);
  480.                     memset(trian->walls + trian->maxwalls, 0, sizeof(lerpWall_t) * DEFAULT_MAX_LERP_WALLS);     // clear the new block
  481.                     trian->maxwalls += DEFAULT_MAX_LERP_WALLS;
  482.                 }
  483.  
  484.                 wall = &trian->walls[trian->numwalls];
  485.                 trian->numwalls++;
  486.  
  487.                 VectorScale(p->normal, 10000.0, delta);
  488.  
  489.                 VectorCopy(g_dvertexes[g_dedges[abs(edgenum)].v[0]].point, p0);
  490.                 VectorCopy(g_dvertexes[g_dedges[abs(edgenum)].v[1]].point, p1);
  491.  
  492.                 // Adjust for origin-based models
  493.                 // technically we should use the other faces g_face_offset entries
  494.                 // If they are nonzero, it has to be from the same model with
  495.                 // the same offset, so we are cool
  496.                 VectorAdd(p0, g_face_offset[facenum], p0);
  497.                 VectorAdd(p1, g_face_offset[facenum], p1);
  498.  
  499.                 VectorAdd(p0, delta, wall->vertex[0]);
  500.                 VectorAdd(p1, delta, wall->vertex[1]);
  501.                 VectorSubtract(p1, delta, wall->vertex[2]);
  502.                 VectorSubtract(p0, delta, wall->vertex[3]);
  503.  
  504.                 {
  505.                     vec3_t          delta1;
  506.                     vec3_t          delta2;
  507.                     vec3_t          normal;
  508.                     vec_t           dist;
  509.  
  510.                     VectorSubtract(wall->vertex[2], wall->vertex[1], delta1);
  511.                     VectorSubtract(wall->vertex[0], wall->vertex[1], delta2);
  512.                     CrossProduct(delta1, delta2, normal);
  513.                     VectorNormalize(normal);
  514.                     dist = DotProduct(normal, p0);
  515.  
  516.                     VectorCopy(normal, wall->plane.normal);
  517.                     wall->plane.dist = dist;
  518.                 }
  519.             }
  520.         }
  521.     }
  522. }
  523.  
  524. // =====================================================================================
  525. //  AllocTriangulation
  526. // =====================================================================================
  527. static lerpTriangulation_t* AllocTriangulation()
  528. {
  529.     lerpTriangulation_t* trian = (lerpTriangulation_t*)calloc(1, sizeof(lerpTriangulation_t));
  530.  
  531.     trian->maxpoints = DEFAULT_MAX_LERP_POINTS;
  532.     trian->maxwalls = DEFAULT_MAX_LERP_WALLS;
  533.  
  534.     trian->points = (patch_t**)calloc(DEFAULT_MAX_LERP_POINTS, sizeof(patch_t*));
  535.  
  536.     trian->walls = (lerpWall_t*)calloc(DEFAULT_MAX_LERP_WALLS, sizeof(lerpWall_t));
  537.  
  538.     hlassume(trian->points != NULL, assume_NoMemory);
  539.     hlassume(trian->walls != NULL, assume_NoMemory);
  540.  
  541.     return trian;
  542. }
  543.  
  544. // =====================================================================================
  545. //  FreeTriangulation
  546. // =====================================================================================
  547. void            FreeTriangulation(lerpTriangulation_t* trian)
  548. {
  549.     free(trian->dists);
  550.     free(trian->points);
  551.     free(trian->walls);
  552.     free(trian);
  553. }
  554.  
  555. // =====================================================================================
  556. //  CreateTriangulation
  557. // =====================================================================================
  558. lerpTriangulation_t* CreateTriangulation(const unsigned int facenum)
  559. {
  560.     const dface_t*  f = g_dfaces + facenum;
  561.     const dplane_t* p = getPlaneFromFace(f);
  562.     lerpTriangulation_t* trian = AllocTriangulation();
  563.     patch_t*        patch;
  564.     unsigned int    j;
  565.     dface_t*        f2;
  566.  
  567.     trian->facenum = facenum;
  568.     trian->plane = p;
  569.     trian->face = f;
  570.  
  571.     for (patch = g_face_patches[facenum]; patch; patch = patch->next)
  572.     {
  573.         AddPatchToTriangulation(trian, patch);
  574.     }
  575.  
  576.     CreateWalls(trian, f);
  577.  
  578.     for (j = 0; j < f->numedges; j++)
  579.     {
  580.         edgeshare_t*    es;
  581.         int             edgenum = g_dsurfedges[f->firstedge + j];
  582.  
  583.         if (edgenum > 0)
  584.         {
  585.             es = &g_edgeshare[edgenum];
  586.             f2 = es->faces[1];
  587.         }
  588.         else
  589.         {
  590.             es = &g_edgeshare[-edgenum];
  591.             f2 = es->faces[0];
  592.         }
  593.  
  594.         if (!es->coplanar && VectorCompare(vec3_origin, es->interface_normal))
  595.         {
  596.             continue;
  597.         }
  598.  
  599.         for (patch = g_face_patches[f2 - g_dfaces]; patch; patch = patch->next)
  600.         {
  601.             AddPatchToTriangulation(trian, patch);
  602.         }
  603.     }
  604.  
  605.     trian->dists = (lerpDist_t*)calloc(trian->numpoints, sizeof(lerpDist_t));
  606. #ifdef HLRAD_HULLU
  607.     //Get rid off error that seems to happen with some opaque faces (when opaque face have all edges 'out' of map)
  608.     if(trian->numpoints != 0)
  609. #endif
  610.     hlassume(trian->dists != NULL, assume_NoMemory);
  611.  
  612.     return trian;
  613. }
  614.